#include "stdafx.h"
#include "OBJFile.h"


OBJFile::OBJFile(void) { }

OBJFile::~OBJFile(void) { }

void OBJFile::load(class Scene *scene, string filename)
{
	ifstream file(filename);
	vector<string> tokens, tokensFace1, tokensFace2, tokensFace3;
	string ligne;
	myObject3D * obj = new myObject3D();
	Object3DGroup * objg = NULL;

	vector<GLfloat> tmp_vertices;
	vector<GLfloat> tmp_normals;
	vector<GLfloat> tmp_textures;
	vector<GLint> tmp_faces;

	if(file)
	{
		while(getline(file, ligne)) 
		{
			split(tokens,ligne,' ');

			if ( tokens.size() == 0 )
				continue;
			else if ( tokens[0] == "g" )
			{
				if (objg != NULL) objg->indexEnd = obj->m-1;

				objg = new Object3DGroup();
				objg->name = tokens[1];
				objg->indexStart = obj->m;
				obj->groups.push_back(objg);
			}
			else if (tokens[0] == "v")
			{
				tmp_vertices.push_back(atof(tokens[1].c_str()));
				tmp_vertices.push_back(atof(tokens[2].c_str()));
				tmp_vertices.push_back(atof(tokens[3].c_str()));
			}
			else if (tokens[0] == "vt")
			{
				tmp_textures.push_back(atof(tokens[1].c_str()));
				tmp_textures.push_back(atof(tokens[2].c_str()));
			}
			else if (tokens[0] == "vn")
			{
				tmp_normals.push_back(atof(tokens[1].c_str()));
				tmp_normals.push_back(atof(tokens[2].c_str()));
				tmp_normals.push_back(atof(tokens[3].c_str()));
			}
			else if (tokens[0] == "f")
			{
				if ( tokens[1].find('/') != string::npos )
				{
					for(int i = 3; i <  tokens.size() ; i++)
					{
						split(tokensFace1, tokens[1], '/');
						split(tokensFace2, tokens[i-1], '/');
						split(tokensFace3, tokens[i], '/');

						obj->indices.push_back(obj->m*3);
						obj->indices.push_back(obj->m*3 + 1);
						obj->indices.push_back(obj->m*3 + 2);
						obj->m++;

						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace1[0].c_str()) - 1)*3    ]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace1[0].c_str()) - 1)*3 + 1]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace1[0].c_str()) - 1)*3 + 2]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace2[0].c_str()) - 1)*3    ]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace2[0].c_str()) - 1)*3 + 1]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace2[0].c_str()) - 1)*3 + 2]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace3[0].c_str()) - 1)*3    ]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace3[0].c_str()) - 1)*3 + 1]);
						obj->vertices.push_back(tmp_vertices[(atoi(tokensFace3[0].c_str()) - 1)*3 + 2]);
						obj->n+=3;

						obj->textures.push_back(tmp_textures[(atoi(tokensFace1[1].c_str()) - 1)*2    ]);
						obj->textures.push_back(tmp_textures[(atoi(tokensFace1[1].c_str()) - 1)*2 + 1]);
						obj->textures.push_back(tmp_textures[(atoi(tokensFace2[1].c_str()) - 1)*2    ]);
						obj->textures.push_back(tmp_textures[(atoi(tokensFace2[1].c_str()) - 1)*2 + 1]);
						obj->textures.push_back(tmp_textures[(atoi(tokensFace3[1].c_str()) - 1)*2    ]);
						obj->textures.push_back(tmp_textures[(atoi(tokensFace3[1].c_str()) - 1)*2 + 1]);
						
						if ( tokensFace1.size() > 2 )
						{
							obj->normals.push_back(tmp_normals[(atoi(tokensFace1[2].c_str()) - 1)*3    ]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace1[2].c_str()) - 1)*3 + 1]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace1[2].c_str()) - 1)*3 + 2]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace2[2].c_str()) - 1)*3    ]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace2[2].c_str()) - 1)*3 + 1]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace2[2].c_str()) - 1)*3 + 2]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace3[2].c_str()) - 1)*3    ]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace3[2].c_str()) - 1)*3 + 1]);
							obj->normals.push_back(tmp_normals[(atoi(tokensFace3[2].c_str()) - 1)*3 + 2]);
						}
						else
						{
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
							obj->normals.push_back(0);
						}
					}					
				}
				else
				{
					for(int i = 3; i <  tokens.size() ; i++)
					{
						tmp_faces.push_back(atoi(tokens[1].c_str()) - 1);
						tmp_faces.push_back(atoi(tokens[i-1].c_str()) - 1);
						tmp_faces.push_back(atoi(tokens[i].c_str()) - 1);
					}	 
				}
			}
			else if ( tokens[0] == "mtllib" )
			{
				string filenamemtl = (filename.substr(0, filename.find_last_of("/"))).c_str() + string("/") + tokens[1];
				loadmtl(scene, filenamemtl);
			}
			else if ( tokens[0] == "usemtl" )
			{
				if (objg != NULL) 
					objg->material = scene->materials[tokens[1]];
				else
					obj->material = scene->materials[tokens[1]];
			}
		}

		if ( obj->indices.size() == 0 )
		{
			obj->indices.insert(obj->indices.end(), tmp_faces.begin(), tmp_faces.end());
			obj->vertices.insert(obj->vertices.end(), tmp_vertices.begin(), tmp_vertices.end());
			obj->n = obj->vertices.size()/3;
			obj->m = obj->indices.size()/3;
		}

		obj->colors.clear();
		for(int i = 0; i < obj->vertices.size(); i+= 3)
		{
			obj->colors.push_back(1);
			obj->colors.push_back(0);
			obj->colors.push_back(0);
		}		

		cout << "nbVertices : " << obj->n << endl;
		cout << "nbIndices : " << obj->m << endl;
		cout << "nbGroups : " << obj->groups.size() << endl;

		if (objg != NULL) objg->indexEnd = obj->m-1;
		scene->objects.push_back(obj);
	}
	else
	{
		cout << "Cant open file" << endl;
	}
}

void OBJFile::loadmtl(class Scene *scene, string filename)
{
	ifstream file(filename);
	vector<string> tokens;
	Material * mtl;
	string ligne;

	if(file)
	{
		while(getline(file, ligne)) 
		{
			split(tokens,ligne,' ');

			if ( tokens.size() == 0 )
				continue;
			else if ( tokens[0] == "newmtl" )
			{
				mtl = new Material();
				mtl->name = tokens[1];

				scene->materials[mtl->name] = mtl;
					
			}
			else if ( tokens[0] == "Ka" )
			{
				GLfloat Ka[4];

				Ka[0] = atof(tokens[1].c_str());
				Ka[1] = atof(tokens[2].c_str());
				Ka[2] = atof(tokens[3].c_str()); 
				Ka[3] = 1; 

				mtl->initKa(Ka);
			}
			else if ( tokens[0] == "Kd" )
			{
				GLfloat Kd[4];

				Kd[0] = atof(tokens[1].c_str());
				Kd[1] = atof(tokens[2].c_str());
				Kd[2] = atof(tokens[3].c_str()); 
				Kd[3] = 1; 

				mtl->initKd(Kd);
			}
			else if ( tokens[0] == "Ks" )
			{
				GLfloat Ks[4];

				Ks[0] = atof(tokens[1].c_str());
				Ks[1] = atof(tokens[2].c_str());
				Ks[2] = atof(tokens[3].c_str()); 
				Ks[3] = 1; 

				mtl->initKs(Ks);
			}
			else if ( tokens[0] == "Ns" )
			{
				mtl->initSh(atof(tokens[1].c_str()));
			}
			else if ( tokens[0] == "map_Kd" )
			{
				mtl->texture = new myTexture();
				string filenametexture = (filename.substr(0, filename.find_last_of("/"))).c_str() + string("/") + tokens[1];
				mtl->texture->readTexture(filenametexture.c_str());
			}
			else if ( tokens[0] == "map_nm" )
			{
				mtl->bump = new myTexture();
				string filenametexture = (filename.substr(0, filename.find_last_of("/"))).c_str() + string("/") + tokens[1];
				mtl->bump->readTexture(filenametexture.c_str());
			}
		}
	}
	else
	{
		cout << "Cant open file" << endl;
	}
}

